#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2017/5/7 下午10:27
# @Author  : zhangzhen
# @Site    : 
# @File    : pos.py
# @Software: PyCharm
import string
import sys
import random
import numpy as np
from collections import defaultdict
import pandas as pd
from sklearn.multiclass import OneVsOneClassifier
from sklearn.svm import LinearSVC
from sklearn.svm import SVC
from com.corpus import corpus
from sklearn.multiclass import OneVsRestClassifier
from sklearn.feature_extraction.text import TfidfTransformer
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import chi2

from matplotlib.font_manager import FontProperties
from matplotlib.ticker import MultipleLocator, FormatStrFormatter
import matplotlib.pyplot as plt
try:
    reload(sys)
    sys.setdefaultencoding('utf-8')
except:
    pass


class pos_utils():
    """pos维度 11551"""
    @staticmethod
    def load_pos():
        vectorizer = CountVectorizer()  # 该类会将文本中的词语转换为词频矩阵，矩阵元素a[i][j] 表示j词在i类文本下的词频
        transformer = TfidfTransformer()  # 该类会统计每个词语的tf-idf权值
        texts = []
        y = []
        for i in range(7):
            c = corpus.corpus('../../data/', str(i))
            pos_corpus = c.get_tag_corpus()
            for line in pos_corpus:
                texts.append(line)
                y.append(i)
        tfidf = transformer.fit_transform(vectorizer.fit_transform(texts))
        # word = vectorizer.get_feature_names() # 获取对应特征值
        X = tfidf.toarray()
        return X, np.array(y)


def plot(macro_p,macro_r,micro_p,micro_r,tops):

    x = [i for i, v in enumerate(tops)]
    # 创建绘图对象，figsize参数可以指定绘图对象的宽度和高度，单位为英寸，一英寸=80px
    plt.figure(figsize=(8, 4))
    # 在当前绘图对象中画图（x轴,y轴,给所绘制的曲线的名字，画线颜色，画线宽度）
    # 宏平均(macro-average)和微平均(micro-average)
    #
    plt.plot(x, macro_p, 'ro-', label="$macro-precision$", color="red", linewidth=2)
    plt.plot(x, macro_r, 'gv-', label="$macro-recall$", color="green", linewidth=2)
    plt.plot(x, 2*macro_p*macro_r/(macro_p+macro_r), 'bs-', label="$macro-F$", color="blue", linewidth=2)
    plt.plot(x, micro_p, 'ch-', label="$micro-average$", color="black", linewidth=2)
    # plt.plot(x, micro_r, 'mD-', label="$micro-recall$", color="cyan", linewidth=2)
    # plt.plot(x, 2*micro_p*micro_r/(micro_p+micro_r), 'r^-', label="$micro-F$", color="magenta", linewidth=2)
    # X轴的文字
    # plt.xlabel("Time(s)")
    # group_labels = ['10', '40', '80', '100', '120', '150', '180', '200', '220']
    plt.xticks(x, tops, rotation=0)
    # Y轴的文字
    # plt.ylabel("Volt")

    # 图表的标题
    plt.title(u'Classification of 3-POS Features with Different Dimensions')
    # Y轴的范围
    plt.xlim(0, len(tops))
    plt.ylim(0.05, 0.6)
    # 显示图示
    plt.legend()
    plt.grid()
    # 显示图
    plt.show()

if __name__ == '__main__':
    # 11551
    X, y = pos_utils.load_pos()

    num = 24
    macro_p = np.zeros(num)
    macro_r = np.zeros(num)
    micro_p = np.zeros(num)
    micro_r = np.zeros(num)

    # top = 1000  # 特征维度数
    train_num = 400
    test_num = 100  # 文本测试集
    times = 50
    for time in range(times):
        tops = []
        tmp_macro_p = []
        tmp_macro_r = []
        tmp_micro_p = []
        tmp_micro_r = []
        for top in range(20, 500, 20):
            tops.append(top)
            # 卡方特征选取 前k个特征
            X_new = SelectKBest(chi2, k=top).fit_transform(X, y)

            # 随机选取训练数据 300
            train_index = []
            test_index = []
            type_dict = defaultdict(list)
            # 随机选取各类数据100个
            for k, v in enumerate(y):
                type_dict[v].append(k)
            for k, v in type_dict.iteritems():
                if train_num >= len(type_dict[k]):
                    train_index.extend(type_dict[k])
                else:
                    train_index.extend(random.sample(type_dict[k], train_num))
                test_index.extend(random.sample(type_dict[k], test_num))

            X_train = np.array([X_new[i] for i in train_index])
            y_train = np.array([y[i] for i in train_index])

            X_test = np.array([X_new[i] for i in test_index])
            y_test = np.array([y[i] for i in test_index])

            acc = np.ones(7)
            err = np.ones(7)
            res = OneVsOneClassifier(LinearSVC(random_state=0)).fit(X_train, y_train).predict(X_test)
            # res = OneVsRestClassifier(LinearSVC(random_state=0)).fit(X_train, y_train).predict(X_test)
            # print res
            for i, re in enumerate(res):
                if re == y_test[i]:
                    acc[re] += 1
                else:
                    err[re] += 1
            # 宏平均
            ap = np.sum(acc / (err + acc)) / 7
            ar = np.sum(acc / test_num) / 7
            tmp_macro_p.append(ap)
            tmp_macro_r.append(ar)

            # 微平均
            ip = np.sum(acc) / (np.sum(acc) + np.sum(err))
            ir = np.sum(acc) / (7 * test_num)
            tmp_micro_p.append(ip)
            tmp_micro_r.append(ir)

        macro_p += np.array(tmp_macro_p)
        macro_r += np.array(tmp_macro_r)
        micro_p += np.array(tmp_micro_p)
        micro_r += np.array(tmp_micro_r)

    macro_p = macro_p / times
    macro_r = macro_r / times
    micro_p = micro_p / times
    micro_r = micro_r / times

    print "维度", tops
    print "宏准确", macro_p
    print "宏召回率", macro_r
    print "宏F值", 2 * macro_p * macro_r / (macro_p + macro_r)
    print "微准确率", micro_p
    print "微召回率", micro_r
    print "微F值", 2 * micro_p * micro_r / (micro_p + micro_r)
    # 绘图操作
    # 绘图操作
    plot(macro_p, macro_r, micro_p, micro_r, tops)
